package com.yazi.mxz.gather.main.goods;

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;



import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.util.EntityUtils;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlText;
import com.yazi.mxz.gather.common.App;
import com.yazi.mxz.gather.common.App.PicObject;
import com.yazi.mxz.gather.entity.enums.ProcessType;
import com.yazi.mxz.gather.entity.http.Ssls8ResBody4Cat;
import com.yazi.mxz.gather.entity.http.Ssls8ResBody4Detail;
import com.yazi.mxz.gather.entity.http.Ssls8ResBody4List;
import com.yazi.mxz.gather.entity.http.Ssls8ResBody4Pic;
import com.yazi.mxz.gather.entity.http.Ssls8ResBody4Detail.Li;
import com.yazi.mxz.gather.entity.http.Ssls8ResBody4List.Div;
import com.yazi.mxz.gather.entity.repository.ProcessLog;
import com.yazi.mxz.gather.entity.repository.Product;
import com.yazi.mxz.gather.repository.ProcessLogRepository;
import com.yazi.mxz.gather.repository.ProductRepository;

/**
 * 食尚联食吧
 * http://ssls8.com
 * @author mo_yq5
 * @date 2015-8-12
 */
public class Ssls8Com extends Thread {
	
	private CloseableHttpAsyncClient httpclient;
	private ProcessLogRepository logRepository;
	private ProductRepository productRepository;
	private ObjectMapper om;
	
	
	public Ssls8Com() {
		init();
	}
	
	public Ssls8Com(int startPage, int endPage) {
		init();
		ProcessLog log = logRepository.findOne(ProcessType.SSLS8.ordinal());
		if (null == log) {
			log = new ProcessLog();
			log.setId(ProcessType.SSLS8.ordinal());
			log.setCur((long)startPage);
			log.setEnd((long)endPage);
			log.setCount(0);
			logRepository.insert(log);
		} else {
			log.setCur((long)startPage);
			log.setEnd((long)endPage);
			logRepository.save(log);
		}
	}
	
	public void init() {
		
		productRepository = App.context.getBean(ProductRepository.class);
		logRepository = App.context.getBean(ProcessLogRepository.class);
		
		httpclient = HttpAsyncClients.createDefault();
		httpclient.start();
		
		om = new XmlMapper();
		om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
	}

	@Override
	public void run() {
		
		ProcessLog log = logRepository.findOne(ProcessType.SSLS8.ordinal());
		if (null == log) {
			System.out.println(ProcessType.SSLS8 + "日志不存在");
			return;
		}
		boolean isContinue = false;
		
		try {
			
			
			while (true) {
				
				if (log.getCur() > log.getEnd()) {
					isContinue = false;
					break;
				}
				
				barcodeInfo(log.getCur());
				
				log.setCur(log.getCur() + 1);
				logRepository.save(log);
			
				sleep(200);
			}
			
		} catch (SocketException e) {
			e.printStackTrace();
			isContinue = true;
			
		} catch (Exception e1) {
			e1.printStackTrace();
			
		} 
		if (isContinue) {
			run();
		} else {
			System.out.println("执行结束！");
		}
	}
	
	private String barcodeInfo(long pageNum) throws JsonParseException, JsonMappingException,
			IOException, InterruptedException, ExecutionException {
		
		System.out.println("PageNum:" + pageNum);
		
		final HttpGet req = new HttpGet("http://ssls8.com/search.php?sort=goods_id&order=ASC&page=" + pageNum);
		Future<HttpResponse> future = httpclient.execute(req, null);
		HttpResponse res = future.get();
		
		System.out.println(req.getRequestLine() + "->" + res.getStatusLine());
		
		String body = EntityUtils.toString(res.getEntity(), "utf-8");
		if (body.isEmpty()) {
			System.out.println("无响应内容!");
			return null;
		}
		
		int startIndex = body.indexOf("<form action=\"compare.php\"");// <form action="compare.php"
		int endIndex = body.indexOf("</form>", startIndex) + 7;
		body = body.substring(startIndex, endIndex)
				.replaceAll("alt=\"[\\s|\\S]{0,100} class=\"goodsimg\"", "class=\"goodsimg\"") // 去掉alt, 内容可能含有<或>
				.replaceAll("&lt;", "(")
				.replaceAll("&gt;", ")")
				.replaceAll("<\\.\\.\\.", "")
				.replaceAll("<牛轧\\.\\.\\.", "")
				.replaceAll("&nbsp;", "")
				.replaceAll("&amp;", "")
				.replaceAll("&", "");
		
		//System.out.println(body);
		
		Ssls8ResBody4List ssls4List = om.readValue(body, Ssls8ResBody4List.class);
		List<Div> divs = ssls4List.getDiv().getDiv().getDivs();
		StringBuffer goodsInfo = new StringBuffer();
		String proId, name, barcode, pic, price, catName, spec, brandName, area, bigPic;
		for (Div div : divs) {
			proId = div.getA().getHref().substring(13);// 详情地址如: goods.php?id=369
			pic = div.getA().getImg().getSrc();// 图片
			if (pic.equals("images/no_picture.gif")) {
				pic = null;
			} else {
				pic = "http://ssls8.com/" + pic;
			}
			
			Map<String, String> detail = getDetailInfo(proId);
			
			barcode = detail.get("barcode");
			name = detail.get("name");
			catName = detail.get("catName");
			spec = detail.get("spec");
			price = detail.get("price");
			brandName = detail.get("brandName");
			area = detail.get("area");
			bigPic = detail.get("bigPic");
			
			if (null == barcode || !App.checkBarCode(barcode)) {
				System.out.println("无效条码: " + barcode + " -> " + proId + " -> " + name);
				continue;
			}
			
			goodsInfo = new StringBuffer();
			goodsInfo.append("\r\nID:" + proId);
			goodsInfo.append("\r\n条码:" + barcode);
			goodsInfo.append("\r\n名称:" + name);
			goodsInfo.append("\r\n单价:" + price);
			goodsInfo.append("\r\n分类:" + catName);
			goodsInfo.append("\r\n规格:" + spec);
			goodsInfo.append("\r\n品牌:" + brandName);
			goodsInfo.append("\r\n产地:" + area);
			goodsInfo.append("\r\n小图:" + pic);
			goodsInfo.append("\r\n大图:" + bigPic);
			System.out.println(goodsInfo);
			
			App.PicObject picObj = new App.PicObject();
			
			if (null != pic ) {
				App.setPic(pic, picObj);
			}
			if (null != bigPic) {
				App.setPic(bigPic, picObj);
			}
			
			if (!productRepository.exists(barcode)) {
				
				System.out.println("添加: " + barcode + " -> " + name);
				
				
				Product product = new Product();

				product.setArea(area);
				product.setBarcode(barcode);
				product.setBigPic(App.saveGoodsBigImageV1(picObj.getBigPic()));
				product.setBrandName(brandName);
				product.setCatName(catName);
				//product.setFacCode(items.getFacCode());
				//product.setFacName(items.getFacName());
				product.setIsCheckName(true);
				product.setMidPic(App.saveGoodsMiddleImageV1(picObj.getMidPic()));
				product.setName(name);
				//product.setSpell(rs.getString("pinyin"));
				product.setPic(App.saveGoodsImageV1(picObj.getPic()));
				product.setPrice(price);
				//product.setUnit(unit);
				product.setSource("ssls8.com");
				product.setSpec(spec);
				//product.setSupplier(items.getSupplier());
				product.setSysRemark(proId);

				productRepository.insert(product);

			} else {
				
				System.out.println("修改: " + barcode + " -> " + name);

				Product product = productRepository.findOne(barcode);
				
				if (null == product.getBigPic()) {
					product.setBigPic(App.saveGoodsBigImageV1(picObj.getBigPic()));
				}
				if (null == product.getMidPic()) {
					product.setMidPic(App.saveGoodsMiddleImageV1(picObj.getMidPic()));
				}
				if (null == product.getPic()) {
					product.setPic(App.saveGoodsImageV1(picObj.getPic()));
				}
				
				
				if (null != area && null == product.getArea()) {
					product.setArea(area);
				}
				if (null != brandName && null == product.getBrandName()) {
					product.setBrandName(brandName);
				}
				if (null != catName && null == product.getCatName()) {
					product.setCatName(catName);
				}
				if (null != name && null == product.getName()) {
					product.setName(name);
				}
				if (null != price && null == product.getPrice()) {
					product.setPrice(price);
				}
				/*if (null != unit && null == product.getUnit()) {
					product.setUnit(unit);
				}*/
				if (null != spec && null == product.getSpec()) {
					product.setSpec(spec);
				}
				
				productRepository.save(product);

			}
		}
		
		return null;
	}
	
	private Map<String, String> getDetailInfo(String proId) throws InterruptedException, ExecutionException, ParseException, IOException {

		final HttpGet req = new HttpGet("http://ssls8.com/goods.php?id="+ proId);
		Future<HttpResponse> future = httpclient.execute(req, null);
		HttpResponse res = future.get();
		
		System.out.println(req.getRequestLine() + "->" + res.getStatusLine());
		
		StringBuffer bodySb = new StringBuffer(EntityUtils.toString(res.getEntity(), "utf-8"));
		if (bodySb.length() == 0) {
			System.out.println("无响应内容!");
			return null;
		}
		
		// 分类相关
		int start = bodySb.indexOf("<div id=\"ur_here\" class=\"f_l\">");// <div id="ur_here" class="f_l">
		int end = bodySb.indexOf("<div class=\"pre f_r\">");// <div class="pre f_r">
		StringBuffer catSb = new StringBuffer(bodySb.substring(start, end));
		
		// 标题内容用<![CDATA[[..]]>包住,因为有时候会含有特殊字符
		catSb.insert(catSb.lastIndexOf("</a>") + 4, "<![CDATA[");
		catSb.insert(catSb.lastIndexOf("</div>"), "]]>");
		
		String catStr = catSb.toString()
				.replaceAll("<code>&gt;</code>", "")
				.replaceAll("&", "");
		
		//System.out.println(catStr);
		Ssls8ResBody4Cat ssls4Cat = om.readValue(catStr, Ssls8ResBody4Cat.class);
		List<com.yazi.mxz.gather.entity.http.Ssls8ResBody4Cat.A> as = ssls4Cat.getAs();
		as.remove(0);// 删除"首页"
		String catName = "";
		for (com.yazi.mxz.gather.entity.http.Ssls8ResBody4Cat.A a : as) {
			catName += (catName.isEmpty() ? "":",") +  a.getText();// 各级分类间用,号
		}
		
		// 大图<a></a>
		String bigPic;
		String str = "<div class=\"imgInfo\">";
		start = bodySb.indexOf(str) + str.length();// <div class="imgInfo">
		
		if (bodySb.indexOf("class=\"thumb\"", start) > -1) {
			end = bodySb.indexOf("</a>", start) + 4;
			String bigPicStr = bodySb.substring(start, end)
					.replaceAll("title=\"[\\s|\\S]* rel=\"thumb\\-change", "rel=\"thumb-change") // 去掉title
					.replaceAll("alt=\"[\\s|\\S]* class=\"thumb\"", "class=\"thumb\"") // 去掉alt
					.replaceAll("&nbsp;", "")
					.replaceAll("&lt;", "(")
					.replaceAll("&gt;", ")");
			
			//System.out.println(bigPicStr);
			Ssls8ResBody4Pic ssls4Pic = om.readValue(bigPicStr, Ssls8ResBody4Pic.class);
			bigPic = "http://ssls8.com/" + ssls4Pic.getImg().getSrc();
		} else {
			bigPic = null;
		}
		
		
		// 其它详情<form>...</form>
		start = bodySb.indexOf("<form action=\"javascript:addToCart");// <form action="javascript:addToCart
		end = bodySb.indexOf("<div class=\"blank5 clearfix\">");// <div class="blank5 clearfix"> 
		StringBuffer detailSb =  new StringBuffer(bodySb.substring(start, end));
		
		// 标题内容用<![CDATA[[..]]>包住,因为有时候会含有特殊字符
		detailSb.insert(detailSb.indexOf("<h1>") + 4, "<![CDATA[");
		detailSb.insert(detailSb.indexOf("</h1>"), "]]>");
		
		String detailStr = detailSb.toString()
				// <li></li>的内容用<!CDATA[[...]]>包裹
				.replaceAll("<li class=\"clearfix\">", "<li class=\"clearfix\"><![CDATA[")
				.replaceAll("<li class=\"clearfix numberss\">", "<li class=\"clearfix numberss\"><![CDATA[")
				.replaceAll("</li>", "]]></li>") 
				// 删除内容
				.replaceAll("<div style=\"height:5px; clear:both; font-size:0;\">&nbsp;</div>", "")
				.replaceAll("&nbsp;", "")
				.replaceAll("&lt;", "(")
				.replaceAll("&gt;", ")")
				.replaceAll("&", "");
		
		// 去除注释<!-- -->
		String subString;// 注释内容
		while(true) {
			start = detailStr.indexOf("<!--");
			if (start == -1) {
				break;
			} 
			subString = detailStr.substring(start, detailStr.indexOf("-->", start) + 3);
			detailStr = detailStr.replace(subString, "");
		}
		// 15977767448
		//System.out.println(detailStr);
		Ssls8ResBody4Detail ssls4Detail = om.readValue(detailStr, Ssls8ResBody4Detail.class);
		
		String area = null, brandName = null, name = null, spec = null, barcode = null, price = null;
		
		// 台湾张君雅小妹妹（巧克力甜甜圈）45g*15/件 去掉*号及后面的内容(该站的批发发,我们不需要后面的内容)
		name = ssls4Detail.getH1().getText().trim().replaceAll("\\*[\\s|\\S]*", "");// 名称
		
		List<Li> lis = ssls4Detail.getUl().getLis();
		String text;
		for (Li li : lis) {
			
			text = li.getText();
			if (text.indexOf("商品条码：") > -1) {
				barcode = text.replaceAll("商品条码：", "")
						// 可能存在的其它字符
						.replaceAll(" ", "")
						.replaceAll("’", "")
						.replaceAll("\\-", "");
				
			} else if (text.indexOf("产地：") > -1) {
				area = text.replaceAll("产地：", "").trim();
				
			} else if (text.indexOf("规格：") > -1) {
				spec = text.replaceAll("规格：", "")
						.replaceAll("\\*[\\s|\\S]*", "") // 如:400g*12/件 *及后面的内容不要 
						.trim();
				
			} else if (text.indexOf("产品品牌：") > -1) {
				brandName = om.readValue(text.replaceAll("产品品牌：", ""), A.class)
						.getText()
						.trim();
				
			}  else if (text.indexOf("市场价：") > -1) {
				price = om.readValue(text.replaceAll("市场价：", ""), Font.class)
						.getText()
						.replaceAll("￥", "")// 去掉￥号
						.trim();
			} 
			
		}
		
		// 从另一个地方找条码
		if (null == barcode) {
			str = "<td bgcolor=\"#FFFFFF\" align=\"left\" width=\"30%\" class=\"f1\">[商品条码]</td>";
			start = bodySb.indexOf(str) + str.length();
			if (start > -1) {
				end = bodySb.indexOf("</td>", start) + 5;
				try {
				barcode = om.readValue(bodySb.substring(start, end), Td.class).getText()
						.replaceAll(" ", "")
						.replaceAll("\\-", "");
				} catch (Exception e) {}
			}
		}
		
		Map<String, String> detail = new HashMap<String, String>();
		detail.put("barcode", barcode);
		detail.put("name", name);
		detail.put("catName", catName);
		detail.put("spec", spec);
		detail.put("price", price);
		detail.put("brandName", brandName);
		detail.put("area", area);
		detail.put("bigPic", bigPic);
		return detail;
	}
	
	/**
	 * 分类
	 * @author mo_yq5
	 * @date 2015-8-14
	 */
	public static class A {
		@JacksonXmlText
		String text;

		public String getText() {
			return text;
		}

		public void setText(String text) {
			this.text = text;
		}
	}
	/**
	 * 价格
	 * @author mo_yq5
	 * @date 2015-8-14
	 */
	public static class Font {
		@JacksonXmlText
		String text;

		public String getText() {
			return text;
		}

		public void setText(String text) {
			this.text = text;
		}
	}
	
	/**
	 * 条码2
	 * @author mo_yq5
	 * @date 2015-8-14
	 */
	public static class Td {
		@JacksonXmlText
		String text;

		public String getText() {
			return text;
		}

		public void setText(String text) {
			this.text = text;
		}
	}
}
